/*
*  Copyright (c) 2023 Otávio Santana and others
*   All rights reserved. This program and the accompanying materials
*   are made available under the terms of the Eclipse Public License v1.0
*   and Apache License v2.0 which accompanies this distribution.
*   The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
*   and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php.
*
*   You may elect to redistribute this code under either of these licenses.
*
*   Contributors:
*
*   Otavio Santana
*/
package {{packageName}};

import org.eclipse.jnosql.mapping.metadata.ConstructorMetadata;
import org.eclipse.jnosql.mapping.metadata.FieldMetadata;
import org.eclipse.jnosql.mapping.metadata.InheritanceMetadata;
import org.eclipse.jnosql.lite.mapping.metadata.LiteEntityMetadata;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;


import static java.util.function.Function.identity;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

import javax.annotation.processing.Generated;

@Generated(value = "Lite implementation of EntityMetadata with {{className}}", date = "2023-08-05T06:15:00.004923")
public final class {{className}} implements LiteEntityMetadata {

    private final List<FieldMetadata> fields;

    private final InheritanceMetadata inheritance;
    
    private final ConstructorMetadata constructor;

    public {{className}}() {
        this.fields = new ArrayList<>();
        {{#fields}}
        this.fields.add(new {{.}}());
        {{/fields}}
        {{#inheritanceParameter}}
        this.inheritance = new InheritanceMetadata({{{inheritanceParameter}}});
        {{/inheritanceParameter}}
        {{^inheritanceParameter}}
        this.inheritance = null;
        {{/inheritanceParameter}}
        {{#constructorClassName}}
            this.constructor = new  {{constructorClassName}}();
        {{/constructorClassName}}
        {{^constructorClassName}}
        this.constructor = org.eclipse.jnosql.lite.mapping.metadata.DefaultConstructorMetadata.EMPTY;
        {{/constructorClassName}}
    }

    @Override
    public String name() {
        return "{{name}}";
    }

    @Override
    public String className() {
        return "{{entityQualified}}";
    }

    @Override
    public String simpleName() {
        return "{{entity}}";
    }


    @Override
    public <T> T newInstance() {
        {{^notConcrete}}
         return (T)new {{entity}}();
        {{/notConcrete}}
       {{#notConcrete}}
         throw new UnsupportedOperationException("You cannot use the constructor method to the class " +
           "{{entityQualified}}");
       {{/notConcrete}}
    }

    @Override
    public ConstructorMetadata constructor() {
        return constructor;
    }

    @Override
    public Class<?> type() {
        return {{entity}}.class;
    }

    @Override
    public List<FieldMetadata> fields() {
        return Collections.unmodifiableList(fields);
    }

    @Override
    public List<String> fieldsName() {
        return fields().stream()
                .map(FieldMetadata::fieldName)
                .collect(collectingAndThen(toList(), Collections::unmodifiableList));
    }

    @Override
    public String columnField(String javaField) {
        Objects.requireNonNull(javaField, "javaField is required");
        return fields().stream()
                .filter(f -> javaField.equals(f.fieldName()))
                .map(FieldMetadata::name)
                .findFirst().orElse(javaField);
    }

    @Override
    public Optional<FieldMetadata> fieldMapping(String javaField) {
        Objects.requireNonNull(javaField, "javaField is required");
        return fields().stream()
                .filter(f -> javaField.equals(f.fieldName()))
                .findFirst();
    }

    @Override
    public Map<String, FieldMetadata> fieldsGroupByName() {
        return fields().stream()
                .collect(toMap(FieldMetadata::name, identity()));
    }

    @Override
    public Optional<FieldMetadata> id() {
        return fields().stream()
                .filter(FieldMetadata::isId)
                .findFirst();
    }

    @Override
    public boolean hasEntityName() {
         return Objects.isNull(inheritance) || isInheritance();
    }

    @Override
    public boolean isInheritance() {
          return {{hasInheritanceAnnotation}};
    }

    @Override
    public boolean isEntity() {
        return {{entityAnnotation}};
    }
    @Override
    public Optional<InheritanceMetadata> inheritance() {
        return Optional.ofNullable(inheritance);
    }

}
